﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization;
using System.IO;

namespace SyncLib.Data
{

    public partial class ScopeInfoEx
    {

        [DataMember]
        public TableOfScope[] TableOfScopes { get; set; }
        public SyncDirectionOrder SyncDirection
        {
            get
            {

                return (SyncDirectionOrder)Enum.Parse(typeof(SyncDirectionOrder), Direction);
            }
        }

        public TableOfScope FindTable(string tableName)
        {
            foreach (TableOfScope node in TableOfScopes)
                if (node.TableName.Equals(tableName, StringComparison.InvariantCultureIgnoreCase))
                    return node;
            return null;
        }

        public void LoadTableOfScope()
        {
            SqlDataReader reader = null;
            try
            {
                List<TableOfScope> lstData = new List<TableOfScope>();
                string sql = string.Format("Select * from [{0}].[TableOfScope] WHERE ScopeExId='{1}'", CommonVariable.SyncConfigSchema, ScopeExId);
                reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql);
                while (reader.Read())
                {
                    TableOfScope node = new TableOfScope();
                    node.Populate(reader);
                    lstData.Add(node);
                    node.LoadDependencyTable();
                }
                TableOfScopes = lstData.ToArray();
            }
            catch
            {
                throw;
            }
            finally
            {
                if (reader != null)
                    reader.Close();
            }
        }
        public void Populate(IDataReader myReader)
        {
            Comment = "";
            TemplateName = "";

            ScopeExId = (Guid)myReader["ScopeExId"];
            ScopeName = myReader.ReadString("ScopeName");
            Schema = myReader.ReadString("Schema");
            ServerAssembly = myReader.ReadString("ServerAssembly");
            ServerClass = myReader.ReadString("ServerClass");
            ClientAssembly = myReader.ReadString("ClientAssembly");
            ClientClass = myReader.ReadString("ClientClass");
            ScopeVersion = (int)myReader["ScopeVersion"];
            SchemaVersion = (int)myReader["SchemaVersion"];
            UploadFirst = (bool)myReader["UploadFirst"];
            DownloadFirst = (bool)myReader["DownloadFirst"];
            ClientID = (Guid)myReader["ClientID"];
            if (myReader["Comment"] != DBNull.Value)
                Comment = myReader.ReadString("Comment");
            ScopeType = (int)myReader["ScopeType"];
            Enable = (bool)myReader["Enable"];
            Direction = myReader.ReadString("Direction");
            Ordinal = (int)myReader["Ordinal"];
            AssemblyVersion = (int)myReader["AssemblyVersion"];
            ClientAssemblyVersion = (int)myReader["ClientAssemblyVersion"];
            ClientSchemaVersion = (int)myReader["ClientSchemaVersion"];
            ClientScopeVersion = (int)myReader["ClientScopeVersion"];
            BatchSize = (int)myReader["BatchSize"];
            SyncTimes = (int)myReader["SyncTimes"];
            ConfigTimes = (int)myReader["ConfigTimes"];

            if (myReader["TemplateName"] != DBNull.Value)
                TemplateName = myReader.ReadString("TemplateName");

        }

        public void LoadById(Guid id)
        {
            ScopeExId = id;
            SqlDataReader reader = null;
            try
            {
                List<TableOfScope> lstData = new List<TableOfScope>();
                string sql = string.Format("Select * from [{0}].[ScopeInfoEx] WHERE ScopeExId='{1}'", CommonVariable.SyncConfigSchema, ScopeExId);
                reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql);
                if (reader.Read())
                {
                    Populate(reader);
                }

            }
            catch
            {
                throw;
            }
            finally
            {
                if (reader != null)
                    reader.Close();
            }
        }
        public void Clone()
        {
            Clone(false);
        }
        public void Clone(bool includeList)
        {
            ScopeInfoEx temp = new ScopeInfoEx();
            temp.AssemblyVersion = AssemblyVersion;
            temp.ClientAssembly = ClientAssembly;
            temp.ClientClass = ClientClass;
            temp.ClientID = ClientID;
            temp.Comment = Comment;
            temp.Direction = Direction;
            temp.Enable = Enable;
            temp.Ordinal = Ordinal;
            temp.Schema = Schema;
            temp.SchemaVersion = SchemaVersion;
            temp.ScopeExId = ScopeExId;
            temp.ScopeName = ScopeName;
            temp.ScopeType = ScopeType;
            temp.ScopeVersion = ScopeVersion;
            temp.ServerAssembly = ServerAssembly;
            temp.ServerClass = ServerClass;
            temp.DownloadFirst = DownloadFirst;
            temp.UploadFirst = UploadFirst;
            temp.ClientScopeVersion = ClientScopeVersion;
            temp.ClientSchemaVersion = ClientSchemaVersion;
            temp.ClientAssemblyVersion = ClientAssemblyVersion;
            temp.BatchSize = BatchSize;
            if (includeList)
            {
                temp.TableOfScopes = TableOfScopes;
            }

        }
        public void LoadByNameAndClientId()
        {
            string sql = "SELECT T1.[ScopeExId] " +
"       ,[ScopeName] " +
"       ,[Schema] " +
"       ,[ServerAssembly] " +
"       ,[ServerClass] " +
"       ,[ClientAssembly] " +
"       ,[ClientClass] " +
"       ,T1.[ScopeVersion] " +
"       ,T1.[SchemaVersion] " +
"       ,[Comment] " +
"       ,[ScopeType] " +
"       ,[Direction] " +
"       ,[Ordinal] " +
"       ,T1.[AssemblyVersion] " +
"       ,[TemplateName] " +
"       ,ISNULL(T2.[ClientId],'{1}') [ClientId] " +
"       ,ISNULL(T2.[BatchSize],0) [BatchSize] " +
"       ,ISNULL(T2.[ScopeVersion],0) [ClientScopeVersion] " +
"       ,ISNULL(T2.[AssemblyVersion],0) [ClientAssemblyVersion] " +
"       ,ISNULL(T2.[SchemaVersion],0) [ClientSchemaVersion] " +
"       ,ISNULL(T2.[UploadFirst],1) [UploadFirst] " +
"       ,ISNULL(T2.[DownloadFirst],1) [DownloadFirst] " +
"       ,ISNULL(T2.[Enable],0) [Enable] " +
"        " +
"   FROM [{0}].[ScopeInfoEx] T1 " +
"   LEFT JOIN [{0}].[ClientConfig] T2 " +
"   ON T2.ScopeExid=T1.ScopeExId AND T2.ClientId='{1}' WHERE  T1.SCopeName=N'{2}' ";
            sql = string.Format(sql, CommonVariable.SyncConfigSchema, ClientID, ScopeName);
            using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
            {
                if (reader.Read())
                    Populate(reader);
                LoadTableOfScope();
            }
        }
        public void LoadByScopeAndClientId()
        {
            string sql = "SELECT T1.[ScopeExId] " +
"       ,[ScopeName] " +
"       ,[Schema] " +
"       ,[ServerAssembly] " +
"       ,[ServerClass] " +
"       ,[ClientAssembly] " +
"       ,[ClientClass] " +
"       ,T1.[ScopeVersion] " +
"       ,T1.[SchemaVersion] " +
"       ,[Comment] " +
"       ,[ScopeType] " +
"       ,[Direction] " +
"       ,[Ordinal] " +
"       ,T1.[AssemblyVersion] " +
"       ,[TemplateName] " +
"       ,ISNULL(T2.[ClientId],'{1}') [ClientId] " +
"       ,ISNULL(T2.[BatchSize],0) [BatchSize] " +
"       ,ISNULL(T2.[ScopeVersion],0) [ClientScopeVersion] " +
"       ,ISNULL(T2.[AssemblyVersion],0) [ClientAssemblyVersion] " +
"       ,ISNULL(T2.[SchemaVersion],0) [ClientSchemaVersion] " +
"       ,ISNULL(T2.[UploadFirst],1) [UploadFirst] " +
"       ,ISNULL(T2.[DownloadFirst],1) [DownloadFirst] " +
"       ,ISNULL(T2.[Enable],0) [Enable] " +
"        " +
"   FROM [{0}].[ScopeInfoEx] T1 " +
"   LEFT JOIN [{0}].[ClientConfig] T2 " +
"   ON T2.ScopeExid=T1.ScopeExId AND T2.ClientId='{1}' AND T1.SCopeExId='{2}' ";
            sql = string.Format(sql, CommonVariable.SyncConfigSchema, ClientID, ScopeExId);
            using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
            {
                if (reader.Read())
                    Populate(reader);
                LoadTableOfScope();
            }
        }
    }
    public partial class TableOfScope
    {
        public void Populate(IDataReader myReader)
        {

            TableID = (Guid)myReader["TableID"];
            ScopeExId = (Guid)myReader["ScopeExId"];
            TableName = myReader.ReadString("TableName");
            PrimaryKey = myReader.ReadString("PrimaryKey");
            PreApplyCommand = myReader.ReadString("PreApplyCommand");
            AfterApplyCommand = myReader.ReadString("AfterApplyCommand");
            SolveConfigCommand = myReader.ReadString("SolveConfigCommand");
            SolveConfigType = myReader.ReadString("SolveConfigType");

        }

        public string GetSortExpression()
        {
            return String.Join(",", PrimaryKey.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
        }
        public string[] GetPrimaryColumns()
        {
            return PrimaryKey.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
        }

        [DataMember]
        public DependencyTable[] DependencyTables { get; set; }
        public void LoadDependencyTable()
        {

            SqlDataReader reader = null;
            try
            {
                List<DependencyTable> lstData = new List<DependencyTable>();
                string sql = string.Format("Select * from [{0}].[DependencyTable] where TableId='{1}'", CommonVariable.SyncConfigSchema, TableID);
                reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql);
                while (reader.Read())
                {
                    DependencyTable node = new DependencyTable();
                    node.Populate(reader);
                    lstData.Add(node);
                }
                DependencyTables = lstData.ToArray();
            }
            catch
            {
                throw;
            }
            finally
            {
                reader.Close();
            }
        }
        public DependencyTable FindDependency(string tableName)
        {
            foreach (DependencyTable node in DependencyTables)
                if (node.TableName.Equals(tableName, StringComparison.InvariantCultureIgnoreCase))
                    return node;
            return null;
        }

    }
    public partial class DependencyTable
    {
        public void Populate(IDataReader myReader)
        {

            DepenTableId = (Guid)myReader["DepenTableId"];
            TableID = (Guid)myReader["TableID"];
            TableName = myReader.ReadString("TableName");
            SelectRowCommand = myReader.ReadString("SelectRowCommand");
            PreApplyTableCommand = myReader.ReadString("PreApplyTableCommand");
            PreApplyRowCommand = myReader.ReadString("PreApplyRowCommand");
            ApplyRowCommand = myReader.ReadString("ApplyRowCommand");
            //return obj;
        }
    }

    public static class DAOExtention
    {
        public static string ReadString(this IDataReader reader, string fileName)
        {
            object temp = reader[fileName];
            if (temp == DBNull.Value)
                return string.Empty;
            else
                return temp.ToString();
        }
        public static void Populate(this FileOfScope obj, IDataReader myReader)
        {
            obj.FileId = (Guid)myReader["FileId"];
            obj.ScopeExId = (Guid)myReader["ScopeExId"];
            obj.FileKey = myReader.ReadString("FileKey");
            obj.Path = myReader.ReadString("Path");
        }
        public static void LoadById(this FileOfScope obj, int id)
        {
            obj.FileId = Guid.Empty;
            string sql = string.Format("Select * from [{0}].[FileOfScope] WHERE FileId={1}", CommonVariable.SyncConfigSchema, id);
            using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
            {
                if (reader.Read())
                    obj.Populate(reader);
            }
        }
        public static void Load(this FileOfScope obj, Guid scopeId, string key)
        {
            obj.FileId = Guid.Empty;
            string sql = string.Format("Select * from [{0}].[FileOfScope] WHERE ScopeExId='{1}' AND FileKey='{1}'", CommonVariable.SyncConfigSchema, scopeId, key);
            using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
            {
                if (reader.Read())
                    obj.Populate(reader);
            }
        }

        public static string GetXml(this DataTable tbl)
        {
            using (DataSet ds = new DataSet("Database"))
            {
                using (DataTable temp = tbl.Copy())
                {
                    if (temp.DataSet != null)
                        temp.DataSet.Tables.Remove(temp);

                    ds.Tables.Add(temp);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        ds.WriteXml(ms, XmlWriteMode.WriteSchema);
                        ms.Position = 0;
                        using (StreamReader sr = new StreamReader(ms))
                        {
                            return sr.ReadToEnd();
                        }
                    }
                }
            }

        }
    }
}
